package com.ms3ds.deviceData.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ms3ds.common.core.domain.R;
import com.ms3ds.common.core.utils.DateUtils;
import com.ms3ds.mineInfo.api.RemoteAreaService;
import com.ms3ds.mineInfo.api.RemoteMineService;
import com.ms3ds.mineInfo.api.domain.Area;
import com.ms3ds.mineInfo.api.domain.Mine;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ms3ds.deviceData.mapper.MovingDataMapper;
import com.ms3ds.deviceData.domain.MovingData;
import com.ms3ds.deviceData.service.IMovingDataService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 位移数据Service业务层处理
 * 
 * @author zlw
 * @date 2025-09-21
 */
@Service
public class MovingDataServiceImpl implements IMovingDataService 
{
    @Autowired
    private MovingDataMapper movingDataMapper;

    @Autowired
    private RemoteMineService  remoteMineService;

    @Autowired
    private RemoteAreaService remoteAreaService;
    /**
     * 查询位移数据
     * 
     * @param id 位移数据主键
     * @return 位移数据
     */
    @Override
    public MovingData selectMovingDataById(Long id)
    {
        return movingDataMapper.selectMovingDataById(id);
    }

    /**
     * 查询位移数据列表
     * 
     * @param movingData 位移数据
     * @return 位移数据
     */
    @Override
    public List<MovingData> selectMovingDataList(MovingData movingData)
    {
        return movingDataMapper.selectMovingDataList(movingData);
    }

    /**
     * 新增位移数据
     * 
     * @param movingData 位移数据
     * @return 结果
     */
    @Override
    public int insertMovingData(MovingData movingData)
    {
        return movingDataMapper.insertMovingData(movingData);
    }

    /**
     * 修改位移数据
     * 
     * @param movingData 位移数据
     * @return 结果
     */
    @Override
    public int updateMovingData(MovingData movingData)
    {
        return movingDataMapper.updateMovingData(movingData);
    }

    /**
     * 批量删除位移数据
     * 
     * @param ids 需要删除的位移数据主键
     * @return 结果
     */
    @Override
    public int deleteMovingDataByIds(Long[] ids)
    {
        return movingDataMapper.deleteMovingDataByIds(ids);
    }

    /**
     * 删除位移数据信息
     * 
     * @param id 位移数据主键
     * @return 结果
     */
    @Override
    public int deleteMovingDataById(Long id)
    {
        return movingDataMapper.deleteMovingDataById(id);
    }


    /**
     * 生成符合业务规则的测试数据 - 为所有区域添加数据
     */
    @Override
    @Transactional
    public int addTestMovingDataWithRule() {
        int totalCount = 0;

        // 获取所有矿山信息
        R<List<Mine>> mineResult = remoteMineService.getAllForRemote();
        if (mineResult == null || mineResult.getData() == null || mineResult.getData().isEmpty()) {
            return 0;
        }

        List<Mine> mines = mineResult.getData();

        // 遍历所有矿山
        for (Mine mine : mines) {
            // 获取该矿山的所有区域
            R<List<Area>> areaResult = remoteAreaService.getAreaListByMineIdForRemote(mine.getId());
            if (areaResult != null && areaResult.getData() != null && !areaResult.getData().isEmpty()) {
                List<Area> areas = areaResult.getData();

                // 遍历该矿山的所有区域
                for (Area area : areas) {
                    Long areaId = area.getId();

                    /* ---------- 规则落地 ---------- */
                    MovingData lastData = movingDataMapper.getLastMovingDataByAreaId(areaId);

                    MovingData movingData = new MovingData();
                    movingData.setAreaId(areaId);

                    // 根据lastData是否为空设置xyz位移量
                    if (lastData == null) {
                        // 如果lastData为空，则xyz三个moving均为0附近正负50以内的随机数
                        movingData.setxMoving((long) (RandomUtils.nextFloat(0, 100) - 50));
                        movingData.setyMoving((long) (RandomUtils.nextFloat(0, 100) - 50));
                        movingData.setzMoving((long) (RandomUtils.nextFloat(0, 100) - 50));
                    } else {
                        // 如果lastData不为空，则新的xyz三个moving为lastData的xyz三个moving原值加上附近正负50以内的随机数
                        float newX = (lastData.getxMoving() != null ? lastData.getxMoving() : 0) + RandomUtils.nextFloat(0, 100) - 50;
                        float newY = (lastData.getyMoving() != null ? lastData.getyMoving() : 0) + RandomUtils.nextFloat(0, 100) - 50;
                        float newZ = (lastData.getzMoving() != null ? lastData.getzMoving() : 0) + RandomUtils.nextFloat(0, 100) - 50;

                        movingData.setxMoving((long) newX);
                        movingData.setyMoving((long) newY);
                        movingData.setzMoving((long) newZ);
                    }

                    movingData.setTime(new Date());

                    int result = movingDataMapper.insertMovingData(movingData);
                    totalCount += result;
                }
            }
        }

        return totalCount;
    }

    /**
     * 根据矿山ID获取最新的7条位移数据
     * @param mineId 矿山ID
     * @return 按区域分组的位移数据
     */
    @Override
    public R<Map<String, Object>> getLatestMovingDataByMineId(Long mineId) {
        // 验证矿山是否存在
        R<List<Mine>> mineResult = remoteMineService.getAllForRemote();
        if (mineResult == null || mineResult.getData() == null || mineResult.getData().isEmpty()) {
            return R.fail("未找到矿山信息");
        }

        boolean mineExists = mineResult.getData().stream()
                .anyMatch(mine -> mine.getId().equals(mineId));

        if (!mineExists) {
            return R.fail("指定的矿山不存在");
        }

        // 获取该矿山的所有区域
        R<List<Area>> areaResult = remoteAreaService.getAreaListByMineIdForRemote(mineId);
        if (areaResult == null || areaResult.getData() == null || areaResult.getData().isEmpty()) {
            return R.fail("该矿山下未找到区域信息");
        }

        List<Area> areas = areaResult.getData();
        
        // 创建areaId到areaName的映射
        Map<Long, String> areaIdToNameMap = areas.stream()
                .collect(Collectors.toMap(Area::getId, Area::getAreaName));

        // 初始化数据结构
        Map<String, Object> chartData = new HashMap<>();
        Map<String, Map<String, List<Long>>> xData = new HashMap<>();
        Map<String, Map<String, List<Long>>> yData = new HashMap<>();
        Map<String, Map<String, List<Long>>> zData = new HashMap<>();
        Map<String, Map<String, List<Long>>> idData = new HashMap<>();
        Map<String, List<String>> dateData = new HashMap<>(); // 修改为不按区域分组
        Map<String, List<String>> timeData = new HashMap<>(); // 修改为不按区域分组

        List<String> unifiedDateValues = new ArrayList<>(); // 统一的日期数据
        List<String> unifiedTimeValues = new ArrayList<>(); // 统一的时间数据

        // 遍历所有区域
        for (Area area : areas) {
            Long areaId = area.getId();
            String areaName = area.getAreaName();

            // 查询该区域的位移数据
            MovingData queryMovingData = new MovingData();
            queryMovingData.setAreaId(areaId);
            List<MovingData> movingDataList = movingDataMapper.selectMovingDataList(queryMovingData);

            // 按时间排序并取最新的7条数据
            if (!movingDataList.isEmpty()) {
                List<MovingData> sortedMovingData = movingDataList.stream()
                        .sorted(Comparator.comparing(MovingData::getTime).reversed())
                        .limit(7)
                        .sorted(Comparator.comparing(MovingData::getId)) // 再按ID正序排序
                        .collect(Collectors.toList());

                // 构建各区域数据
                List<Long> ids = new ArrayList<>();
                List<Long> xValues = new ArrayList<>();
                List<Long> yValues = new ArrayList<>();
                List<Long> zValues = new ArrayList<>();

                // 构造统一的 date 和 time 数据（仅第一个区域的时间用于生成基准）
                if (unifiedDateValues.isEmpty() && unifiedTimeValues.isEmpty() && !sortedMovingData.isEmpty()) {
                    for (MovingData data : sortedMovingData) {
                        String dateTimeStr = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", data.getTime());
                        String[] parts = dateTimeStr.split(" ");
                        unifiedDateValues.add(parts[0]); // 日期部分 yyyy-MM-dd
                        unifiedTimeValues.add(parts[1]); // 时间部分 HH:mm:ss
                    }
                    
                    // 处理时间格式，只保留小时，分钟和秒设为00
                    List<String> newUnifiedTimeValues = new ArrayList<>();
                    String[] timeParts = unifiedTimeValues.get(0).split(":");
                    String baseHour = timeParts[0];
                    
                    for (int i = 0; i < unifiedTimeValues.size(); i++) {
                        int hour = Integer.parseInt(baseHour) + i;
                        newUnifiedTimeValues.add(String.format("%02d:00:00", hour));
                    }
                    unifiedTimeValues = newUnifiedTimeValues;
                }

                // 提取ID、XYZ等数据
                for (MovingData data : sortedMovingData) {
                    ids.add(data.getId());
                    xValues.add(data.getxMoving());
                    yValues.add(data.getyMoving());
                    zValues.add(data.getzMoving());
                }

                // 将各区域数据添加到对应类型中
                idData.computeIfAbsent("id", k -> new HashMap<>()).put(areaName, ids);
                xData.computeIfAbsent("x", k -> new HashMap<>()).put(areaName, xValues);
                yData.computeIfAbsent("y", k -> new HashMap<>()).put(areaName, yValues);
                zData.computeIfAbsent("z", k -> new HashMap<>()).put(areaName, zValues);
            }
        }

        // 添加统一的日期和时间数据
        dateData.put("date", unifiedDateValues);
        timeData.put("time", unifiedTimeValues);

        // 组装最终数据结构
        chartData.putAll(xData);
        chartData.putAll(yData);
        chartData.putAll(zData);
        chartData.putAll(idData);
        chartData.putAll(dateData); // 添加统一日期数据
        chartData.putAll(timeData); // 添加统一时间数据

        Map<String, Object> result = new HashMap<>();
        result.put("chartData", chartData);
        return R.ok(result);
    }

}